//package bloodfang;
//import java.util.Arrays;
//
//@Deprecated
//public class CycleCombat extends CycleRogue {
//	
//	private double current_ks_cd = ks_cd;
//	private double current_sb_cd = 180.;
//	private double avg_bg_buff_eviscerate;
//	private double avg_bg_buff;
//	private double ks_uptime;
//	private final double rvs_duration = 24.;
//	private double ar_duration = 15.;
//	private double sb_duration = 12.;
//	
//	public CycleCombat(Stats stats,Attacks attacks){
//		this.stats = stats;
//		this.attacks = attacks;
//		this.stats.getSettings().spec = Spec.Combat;
//	}
//
//	protected void generate_aps(){
//		double last_aps = 0.;
//		aps.clear();
//		
//		double base_ks_cd = ks_cd;
//		double base_sb_cd = 180.;
//		ProcInfo procInfo = null;
//		for(String prefix : Procs.trinket_prefixes){
//			if(stats.hasProc(prefix+"assurance_of_consequence"))
//				procInfo = stats.getProcInfo(prefix+"assurance_of_consequence");
//		}
//		if(procInfo != null){
//			ProcData procData = stats.getProcData().get(procInfo.getProcName());
//			double scale = get_scaling_value(procData,procInfo.getUpgradeLevel());
//			double res = scale * 0.0098999999 / 100;
//			base_ks_cd /= (1. + res);
//			base_sb_cd /= (1. + res);
//		}
//		current_ks_cd = base_ks_cd;
//		current_sb_cd = base_sb_cd;
//		
//		while(true){
//			aps.clear(); // do not remove
//			
//			// global energy_regen which gets modified by globally used attacks
//			// e.g. revealing_strike
//			double energy_regen = get_energy_regen();
//			
//			// revealing strike is used out of every special cycle so it reduces
//			// energy by an avg amount
//			// simple that we use it every 24sec to be on 100% uptime
//			double ec_rvs = stats.getRealEnergyCosts(40);
//			double rvs_per_sec = 1./ this.rvs_duration;
//			aps.add("revealing_strike", rvs_per_sec);
//			energy_regen -= rvs_per_sec * ec_rvs;
//			double extra_evis_per_sec = rvs_per_sec * 1 / 5;
//			energy_regen -= extra_evis_per_sec * (stats.getRealEnergyCosts(35) - 5 * 5);
//			aps.add("eviscerate", extra_evis_per_sec);
//			// rvs_end
//			
//			// we are having 2 different cycles to manage
//			// 1. shadow_blades where we are getting 1 more cp per generator
//			// 2. no shadow_blades, the normal rotation
//			// while we are using ar always with sb we can add the extra energy
//			// on top of the cycle
//			
//			sb_duration = 12.;
//			if(stats.hasSetBonus(SetBonus.T14_4PC))
//				sb_duration += 6.;
//			double ar_in_sb = Math.min(ar_duration, sb_duration);
//			// default is 12sec ar in 12sec sb
//			double ar_left = Math.max(ar_duration - ar_in_sb, 0);
//			// default is 3sec
//			
//			double ar_energy_regen = 12. * (1. + 0.01 * stats.getBuffed(Stat.hst) / RATING.HASTE_CONVERSION_RATING);
//			
//			double pooling_time = pooling_time(energy_regen, 75.);
//			
//			CycleCombatSetup sb_cycle = new CycleCombatSetup();
//			sb_cycle.length = sb_duration;
//			sb_cycle.shadow_blades = true;
//			sb_cycle.ar_length = ar_in_sb;
//			sb_cycle.energy_regen = energy_regen + ar_energy_regen * sb_cycle.ar_length / sb_cycle.length;
//			sb_cycle.flat_extra_energy = pooling_time * energy_regen;
//			
//			CycleCombatSetup normal_cycle = new CycleCombatSetup();
//			normal_cycle.length = current_sb_cd - sb_duration;
//			normal_cycle.shadow_blades = false;
//			normal_cycle.ar_length = ar_left;
//			normal_cycle.energy_regen = energy_regen + ar_energy_regen * normal_cycle.ar_length / normal_cycle.length;
//			normal_cycle.flat_extra_energy = - pooling_time * energy_regen;
//			
//			double wasted_energy_during_sb = 0.0;
//			for(CycleCombatSetup cycle : new CycleCombatSetup[]{sb_cycle,normal_cycle}){		
//				double snd_speed = 1.4;
//				double speed = snd_speed * (1 + 0.01 * stats.getBuffed(Stat.hst) / RATING.HASTE_CONVERSION_RATING);
//				if(stats.hasRaidBuff(RaidBuff.attackspeed_buff))
//					speed *= 1.1;
//				if(stats.getRace() == Race.troll)
//					speed *= 1 + .2 * 10. / 180;
//				if(stats.getRace() == Race.golbin)
//		            speed *= 1.01;
//				speed *= (1 + 0.2 * cycle.ar_length / cycle.length);
//				speed *= (1 + 0.3 * 40. / stats.getSettings().FIGHT_LENGTH);	
//				double total_speed = speed;
//				
//				double mh_hits = 0.;
//				double oh_hits = 0.;
//				double mh_swing_every = stats.getMh().getSpeed()/total_speed;
//				double oh_swing_every = stats.getOh().getSpeed()/total_speed;
//				if(cycle.shadow_blades){
//					mh_hits = cycle.length / mh_swing_every * this.stats.getMhStyleHitChance();
//					oh_hits = cycle.length / oh_swing_every * this.stats.getOhStyleHitChance();
//					aps.add("sb_mh", mh_hits / current_sb_cd);
//					aps.add("sb_oh", oh_hits / current_sb_cd);
//				}else{
//					mh_hits = cycle.length / mh_swing_every * this.stats.getMhHitChance();
//					oh_hits = cycle.length / oh_swing_every * this.stats.getOhHitChance();
//					aps.add("mh", mh_hits / current_sb_cd);
//					aps.add("oh", oh_hits / current_sb_cd);
//				}
//				
//				//System.out.println("mh" + mh_hits);
//				//System.out.println("oh" + oh_hits);
//				
//				// lets find out how much energy we get from main_gauche
//				double proc_chance_oh = stats.getOh().getSpeed()/1.4 * 0.2;
//				double proc_chance_mh = 0.2;
//				double proc_chance_mg = stats.get_mg_proc_chance() * stats.getMhStyleHitChance();
//				// and combat potency
//				double cp_regen = oh_hits * proc_chance_oh * 15.;
//				cp_regen += mh_hits * proc_chance_mg * proc_chance_mh * 15.;
//				double mg_regen = cp_regen;
//				
//				double energy_available = cycle.energy_regen * cycle.length + mg_regen;
//				energy_available += cycle.flat_extra_energy;
//				if(cycle == normal_cycle)
//					energy_available += Math.max(100, wasted_energy_during_sb);
//				
//				//double pos_energy_regen = energy_available / cycle.length;
//				//System.out.println(cycle.shadow_blades + " pos "+ pos_energy_regen);
//				
//				double finisher_size = 5.;
//				double ss_cp = 1.2;
//				if(cycle.shadow_blades)
//					ss_cp += 1.;
//				double ruthlessness = finisher_size * 0.2;
//				double avg_cpg_per_finisher = (finisher_size - ruthlessness) / ss_cp;
//				
//				double cpg_per_snd = avg_cpg_per_finisher;
//				if(stats.getSettings().short_snd)
//					cpg_per_snd = 1.;
//				
//				double base_ec_ss = 50;
//				if(stats.hasSetBonus(SetBonus.T16_2PC))
//					base_ec_ss -= 15 * 0.2;
//				double ec_ss = stats.getRealEnergyCosts(base_ec_ss);
//				double ec_snd = 25;
//				double ec_evi = stats.getRealEnergyCosts(35);
//				double ec_rup = stats.getRealEnergyCosts(25);
//				if(cycle.shadow_blades && stats.hasSetBonus(SetBonus.T15_4PC)){
//					ec_ss = stats.getRealEnergyCosts(base_ec_ss * 0.6);
//					ec_snd = 25 * 0.6;
//					ec_evi = stats.getRealEnergyCosts(35 * 0.6);
//					ec_rup = stats.getRealEnergyCosts(25 * 0.6);
//				}
//					
//				double avg_relentless_strikes = 5. * finisher_size;
//				
//				double snd_duration = 6 + 6 * cpg_per_snd * ss_cp;
//				double rup_duration = 4 + 4 * finisher_size;
//				if(stats.hasSetBonus(SetBonus.T15_2PC)){
//					snd_duration += 6;
//					rup_duration += 4;
//				}
//				
//				double energy_cost = avg_cpg_per_finisher * ec_ss;
//				double energy_cost_rup = energy_cost + ec_rup - avg_relentless_strikes;
//				double energy_cost_evi = energy_cost + ec_evi - avg_relentless_strikes;
//				double energy_cost_snd = ec_ss * cpg_per_snd + ec_snd - 5 * cpg_per_snd * ss_cp;
//				
//				double ruptures = cycle.length / rup_duration;
//
//				if(!stats.getSettings().use_rupture)
//					ruptures = 0.;
//				if(cycle.shadow_blades && stats.getSettings().sync_ar_with_sb && !stats.getSettings().use_rupture_during_sync)
//					ruptures = 0.;
//				double snds = cycle.length / snd_duration;
//				double energy_left_for_evi = energy_available - ruptures * energy_cost_rup;
//				energy_left_for_evi -= snds * energy_cost_snd;
//				
//				double attacks_so_far = (ruptures + snds) * (1 + avg_cpg_per_finisher);
//				double gcd = 1.0;
//				if(cycle.shadow_blades && stats.hasSetBonus(SetBonus.T15_4PC))
//					gcd -= 0.3;
//				// sync_ar_with_sb = true && stats.getGlyphs().contains("adrenaline_rush")
//				if(true)
//					gcd -= 0.2;
//				gcd += stats.getSettings().gcd_latency;
//				
//				double time_left = cycle.length - attacks_so_far * gcd;
//				double sum_attacks_per_evi = avg_cpg_per_finisher + 1;
//				double evis_time_limited = time_left / (sum_attacks_per_evi * gcd);
//				double evis_energy_limited = energy_left_for_evi / energy_cost_evi;
//				
//				double evis = evis_energy_limited;
//				if(evis_time_limited < evis_energy_limited){
//					evis = evis_time_limited;
//					double energy_lost = energy_left_for_evi - evis * energy_cost_evi;
//					//System.out.println(cycle.shadow_blades + " " + energy_lost);
//					wasted_energy_during_sb = energy_lost;
//				}
//				
//				double ss_per_cycle = avg_cpg_per_finisher * (ruptures + evis);
//				ss_per_cycle += cpg_per_snd * snds;
//				double ss_per_sec = ss_per_cycle / current_sb_cd;
//				double evis_per_sec = evis / current_sb_cd;
//				double rupture_applications_per_sec = ruptures / current_sb_cd;
//				aps.add("rupture_applications", rupture_applications_per_sec);
//				
////				System.out.println("current_sb_cd " + current_sb_cd);
////				System.out.println("length " + cycle.length);
////				System.out.println("rup " + ruptures);
////				System.out.println("evis " + evis);
////				System.out.println("snds " + snds);
//				
//				aps.add("sinister_strike", ss_per_sec);
//				aps.add("eviscerate", evis_per_sec);
//			}
//			if(stats.getSettings().use_rupture){
//				//System.out.println("rupture_applications" + aps.get("rupture_applications")/2);
//				aps.add("rupture", 1./2 );
//			}
//			
//			double ks_aps = 7. / current_ks_cd;
//			aps.add("ks_mh", ks_aps);
//			aps.add("ks_oh", ks_aps);
//			
//			double mh_aps = aps.get("mh") + aps.get("sb_mh") + aps.get("sinister_strike") + aps.get("revealing_strike") + aps.get("eviscerate") + aps.get("ks_mh");
//			double mg_aps = mh_aps * this.stats.getMhStyleHitChance() * this.stats.get_mg_proc_chance();
//			double oh_aps = aps.get("oh") + aps.get("sb_oh") + aps.get("ks_oh");
//			aps.add("main_gauche", mg_aps);
//			
//			double ip_aps = (mh_aps + mg_aps) * 0.3;
//			ip_aps += oh_aps * 0.3;
//			
//			aps.add("instant_poison", ip_aps);
//			aps.add("deadly_poison", 1./3);
//			
//			this.procs(mh_aps, oh_aps, ip_aps);
//			
//			if(Math.abs(last_aps - aps.sum()) <  PRECISION)
//				break;
//			last_aps = aps.sum();
//			
//			double avg_reduction = 2 * 5.;
//			double time_between_finisher = 1 / (aps.get("eviscerate") + aps.get("rupture_applications"));
//			double real_cd_reduce_per_sec = 1 + avg_reduction / time_between_finisher;
//			
//			current_ks_cd = base_ks_cd / real_cd_reduce_per_sec;
//			current_sb_cd = base_sb_cd / real_cd_reduce_per_sec;
//			
////			System.out.println("current_ks_cd " + current_ks_cd);
////			System.out.println("current_sb_cd " + current_sb_cd);
//			
//			ks_uptime = 3.0 / current_ks_cd;
//			
//			double bg_singleduration = 1 / (aps.get("sinister_strike") + aps.get("revealing_strike")) * 4;
//			double bg_length = 15 + 3 * bg_singleduration;
//			double bg_uptime_0_10_20 = bg_singleduration / bg_length;
//			double bg_uptime_30 = 15 / bg_length;
//			// this is for every other attack
//			// optimizate would be to save for every single attack
//			// e.g every single sinister strike which buffs are active
//			// but that leads to an simulation
//			avg_bg_buff = (0+0.1+0.2)*bg_uptime_0_10_20+0.3*bg_uptime_30;
//			// with anticipation we can shift 1 evi from the 0 % buff to an 30% buff
//			// so we assume that every 0% evi is with anticipation an 30% evi
//			avg_bg_buff_eviscerate = avg_bg_buff;
//			if(stats.hasTalent(Talent.anticipation)){
//				avg_bg_buff_eviscerate += 0.3 * bg_uptime_30;
//			}
//		}
//	}
//
//	@Override
//	protected double getSpecDamageMod(AttackData ab) {
//		double dmgMod = 1.;
//		if(ab.getAttack().equals("eviscerate")){
//			dmgMod *= (1 + this.avg_bg_buff_eviscerate);
//		}else
//			dmgMod *= (1 + this.avg_bg_buff);
//		// if we use ar and sb together which is in every case the best option, we never buff shadow_blades with ks
//		if(Arrays.asList( "instant_poison","mh","oh","main_gauche" ).contains( ab.getAttack() )){
//			dmgMod *= (1 + 0.5 * this.ks_uptime);
//		}
//		return dmgMod;
//	}
//	
//	@Override
//	protected double getBaseEnergyRegen() {
//		return 12;
//	}
//}
